package test.hdz.testtouch;

import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.hardware.display.IDisplayManager;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.view.WindowManager.LayoutParams;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author hdz
 * @date 2018/11/21
 */
public class MainActivity extends AppCompatActivity {

    public static final int SOURCE_CLASS_BUTTON  = 0x00000001;
    public static final int SOURCE_KEYBOARD      = 0x00000100 | SOURCE_CLASS_BUTTON;
    private static InputManager im;
    private static Method injectInputEventMethod;

    private View mOverlayView = null;

    BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals("test.testtouch.action")) {
                int cmd = intent.getIntExtra("test.testtouch.data", 0);
                if (cmd == 1) {
                    forceLandscape(true);
                } else if (cmd == 0){
                    forceLandscape(false);
                } else if (cmd == 2) {
                    Intent intent1 = new Intent(Intent.ACTION_MAIN);
                    intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent1.addCategory(Intent.CATEGORY_HOME);
                    MainActivity.this.startActivity(intent1);
                } else if (cmd == 3) {
                    Intent intent1 = new Intent(MainActivity.this, MainActivity.class);
                    intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    MainActivity.this.startActivity(intent1);
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView(false, false);

        registerReceiver(mBroadcastReceiver, new IntentFilter("test.testtouch.action"));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                getOverlayPermission();
            }
        }

        try {
            im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
            MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true);
            injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_PORTRAIT) {
            //切换为竖屏
            initView(false,false);
        } else if (newConfig.orientation == this.getResources().getConfiguration().ORIENTATION_LANDSCAPE) {
            //切换为横屏
            initView(false,false);
        }
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(mBroadcastReceiver);
        if (mOverlayView != null) {
            WindowManager mWindow = (WindowManager) getSystemService(WINDOW_SERVICE);
            mWindow.removeView(mOverlayView);
            mOverlayView = null;
        }
        super.onDestroy();
    }

    private void initView(boolean b, boolean landscape) {
        LinearLayout mainLayout = (LinearLayout)findViewById(R.id.mainLayout);
        if (mainLayout == null) {
            return;
        }
        mainLayout.removeAllViews();
        int columnCount = 12;
        int rowCount = 10;
        if (b) {
            if (landscape) {
                columnCount = 6;
                rowCount = 20;
            }
        } else {
            if (getOrientation() == 0 || getOrientation() == 2) {
                columnCount = 6;
                rowCount = 20;
            }
        }
        for (int i=1; i<=rowCount; i++) {
            LinearLayout rowLayout = new LinearLayout(this);
            LinearLayout.LayoutParams rowLP = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            rowLP.setMargins(0, 10, 0, 0);
            rowLayout.setLayoutParams(rowLP);
            mainLayout.addView(rowLayout);
            addButton(rowLayout, columnCount, i);
        }
    }

    private void addButton(LinearLayout rowLayout, int columnCount, int rowIndex) {
        for (int i=1; i<=columnCount; i++) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.weight = 1.0f;
            Button btn = new Button(this);
            final int index = ((rowIndex-1)*columnCount+i);
            btn.setText(""+index);
            btn.setLayoutParams(params);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    switch (index) {
                        case 1:
                            Toast.makeText(MainActivity.this, ""+index+" 播放", Toast.LENGTH_SHORT).show();
                            play1();
                            break;
                        case 2:
                            Toast.makeText(MainActivity.this, ""+index+" 暂停", Toast.LENGTH_SHORT).show();
                            pause1();
                            break;
                        case 3:
                            Toast.makeText(MainActivity.this, ""+index+" 播放/暂停", Toast.LENGTH_SHORT).show();
                            PlayOrPause1();
                            break;
                        case 4:
                            Toast.makeText(MainActivity.this, ""+index+" 播放", Toast.LENGTH_SHORT).show();
                            play2();
                            break;
                        case 5:
                            Toast.makeText(MainActivity.this, ""+index+" 暂停", Toast.LENGTH_SHORT).show();
                            pause2();
                            break;
                        case 6:
                            Toast.makeText(MainActivity.this, ""+index+" 播放/暂停", Toast.LENGTH_SHORT).show();
                            PlayOrPause2();
                            break;
                        default:
                            Toast.makeText(MainActivity.this, ""+index, Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            });
            rowLayout.addView(btn);
        }
    }

    /**
     * 获取当前屏幕方向
     *
     * @return 0/2竖屏，1/3横屏
     */
    private static int getOrientation() {
        try {
            int rotation = -1;
            Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
            try {
                IWindowManager wm = IWindowManager.Stub.asInterface((IBinder)getServiceMethod.invoke(null, new Object[]{"window"}));
                rotation = wm.getRotation();
            } catch (Error localError) {
                Object object = IDisplayManager.Stub.asInterface((IBinder)getServiceMethod.invoke(null, new Object[] { "display" })).getDisplayInfo(0);
                rotation = ((Integer)DisplayInfo.class.getDeclaredField("rotation").get(object)).intValue();
            }
            return rotation;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    private void forceLandscape(boolean b) {
        if (b) {
            WindowManager mWindow = (WindowManager) getSystemService(WINDOW_SERVICE);
            LayoutParams layout = new LayoutParams(0, 0, LayoutParams.TYPE_SYSTEM_OVERLAY, LayoutParams.FLAG_FULLSCREEN
                    | LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.RGBX_8888
            );
            if (mOverlayView == null) {
                mOverlayView = new View(MainActivity.this);
            } else {
                mWindow.removeView(mOverlayView);
            }
            layout.gravity = Gravity.TOP;
            layout.screenOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
            mWindow.addView(mOverlayView, layout);
            initView(true, false);
        } else {
            WindowManager mWindow = (WindowManager) getSystemService(WINDOW_SERVICE);
            LayoutParams layout = new LayoutParams(0, 0, LayoutParams.TYPE_SYSTEM_OVERLAY, LayoutParams.FLAG_FULLSCREEN
                    | LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.RGBX_8888
            );
            if (mOverlayView == null) {
                mOverlayView = new View(MainActivity.this);
            } else {
                mWindow.removeView(mOverlayView);
            }
            layout.gravity = Gravity.TOP;
            layout.screenOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
            mWindow.addView(mOverlayView, layout);
            initView(true, true);
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void getOverlayPermission() {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.setData(Uri.parse("package:" + getPackageName()));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    private void play1() {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.MEDIA_BUTTON");

        KeyEvent down = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, down);
        sendBroadcast(intent);

        KeyEvent up = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, up);
        sendBroadcast(intent);
    }

    private void pause1() {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.MEDIA_BUTTON");

        KeyEvent down = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PAUSE, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, down);
        sendBroadcast(intent);

        KeyEvent up = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PAUSE, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, up);
        sendBroadcast(intent);
    }

    private void PlayOrPause1() {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.MEDIA_BUTTON");

        KeyEvent down = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, down);
        sendBroadcast(intent);

        KeyEvent up = new KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0);
        intent.putExtra(Intent.EXTRA_KEY_EVENT, up);
        sendBroadcast(intent);
    }

    private void play2() {
        try {
            sendKeyEvent(im, injectInputEventMethod, SOURCE_KEYBOARD, KeyEvent.KEYCODE_MEDIA_PLAY, false);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void pause2() {
        try {
            sendKeyEvent(im, injectInputEventMethod, SOURCE_KEYBOARD, KeyEvent.KEYCODE_MEDIA_PAUSE, false);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void PlayOrPause2() {
        try {
            sendKeyEvent(im, injectInputEventMethod, SOURCE_KEYBOARD, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    private static void injectKeyEvent(InputManager im, Method injectInputEventMethod, KeyEvent event) throws InvocationTargetException, IllegalAccessException {
        injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
    }
    private static void sendKeyEvent(InputManager im, Method injectInputEventMethod, int inputSource, int keyCode, boolean shift) throws InvocationTargetException, IllegalAccessException {
        long now = SystemClock.uptimeMillis();
        int meta = shift ? 1 : 0;
        injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 0, keyCode, 0, meta, -1, 0, 0, inputSource));
        injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 1, keyCode, 0, meta, -1, 0, 0, inputSource));
    }
}
